package com.feng.security.dsa;

import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.util.Properties;

import org.apache.commons.codec.binary.Base64;

import com.feng.security.dsa.comon.DSAKeyMan;
import com.feng.security.dsa.comon.SignErrorMessage;
import com.feng.security.dsa.comon.SignatureResult;

public class SignatureMan {

	private DSAKeyMan keyMan;
	private SignatureHelper signHelper;

	public SignatureMan() {
		this.keyMan = new DSAKeyMan();
		this.signHelper = new SignatureHelper();
	}

	/**
	 * 对properties中数据进行DSA加密,生成加密字符串(生成的串中包含sign_type)
	 * 
	 * @param properties
	 * @param privateKey
	 * @param charset
	 * @return
	 */

	public SignatureResult dsaSign(Properties properties, String privateKey,String charset) {
		SignatureResult rt = new SignatureResult();
		try {
			if (properties == null || privateKey.length() < 1) {
				rt.setSuccess(false);
				rt.setErrorMessage(SignErrorMessage.ILLEAGL_PARAMETER);
			}
			if (charset == null)
				charset = "GBK";

			// 获取待加密URL参数，依据字母升序排序
			String toSignString = this.signHelper
					.getSignatureContent(properties);
			// 根据String生成PrivateKey
			PrivateKey prikey = keyMan.getPKCS8PrivateKey(privateKey);
			// 加密数据
			Signature signature = Signature.getInstance("DSA");
			signature.initSign(prikey);
			signature.update(this.signHelper.getContentBytes(toSignString,
					charset));
			byte signBytes[] = signature.sign();
			// 转换成String
			String sign = new String(Base64.encodeBase64(signBytes));
			rt.setSign(sign);
			// 向参数中添加sign信息
			Properties requestProperties = properties;
			requestProperties.setProperty("sign_type", "DSA");
			requestProperties.setProperty("sign", sign);
			// 生成包含加密信息的URL参数
			String signURL = this.signHelper.genSignURL(requestProperties,
					charset);
			rt.setSignURL(signURL);
			rt.setSuccess(true);
		} catch (Exception e) {
			e.printStackTrace();
			rt.setErrorMessage(SignErrorMessage.SYSTEM_ERROR);
		}
		return rt;
	}

	/**
	 * 对properties中数据进行DSA加密,生成加密字符串(生成的串中不包含sign_type)
	 * 
	 * @param properties
	 * @param privateKey
	 * @param charset
	 * @return
	 */

	public SignatureResult dsaSign2(Properties properties, String privateKey,
			String charset) {
		SignatureResult rt = new SignatureResult();
		try {
			if (properties == null || privateKey.length() < 1) {
				rt.setSuccess(false);
				rt.setErrorMessage(SignErrorMessage.ILLEAGL_PARAMETER);
			}
			if (charset == null)
				charset = "GBK";

			// 获取待加密URL参数，依据字母升序排序
			String toSignString = this.signHelper.getSignatureContent(properties);
			// 根据String生成PrivateKey
			PrivateKey prikey = keyMan.getPKCS8PrivateKey(privateKey);
			// 加密数据
			Signature signature = Signature.getInstance("DSA");
			signature.initSign(prikey);
			signature.update(this.signHelper.getContentBytes(toSignString,
					charset));
			byte signBytes[] = signature.sign();
			// 转换成String
			String sign = new String(Base64.encodeBase64(signBytes));
			rt.setSign(sign);
			// 向参数中添加sign信息
			Properties requestProperties = properties;
			//requestProperties.setProperty("sign_type", "DSA");
			requestProperties.setProperty("sign", sign);
			// 生成包含加密信息的URL参数
			String signURL = this.signHelper.genSignURL(requestProperties,
					charset);
			rt.setSignURL(signURL);
			rt.setSuccess(true);
		} catch (Exception e) {
			e.printStackTrace();
			rt.setErrorMessage(SignErrorMessage.SYSTEM_ERROR);
		}
		return rt;
	}
	
	/**
	 * 对properties中指定顺序的数据进行DSA加密,生成加密字符串
	 * 
	 * @param properties(已经排好顺序的)
	 * @param privateKey
	 * @param charset
	 * @return
	 */
	public SignatureResult dsaSignAms(Properties properties, String privateKey,
			String charset) {
		SignatureResult rt = new SignatureResult();
		try {
			if (properties == null || privateKey.length() < 1) {
				rt.setSuccess(false);
				rt.setErrorMessage(SignErrorMessage.ILLEAGL_PARAMETER);
			}
			if (charset == null)
				charset = "GBK";

			// 获取待加密URL参数，依据字母升序排序
			String toSignString = this.signHelper.getSignatureContent(properties);
			System.out.println("To sign string is :"+toSignString);
			// 根据String生成PrivateKey
			PrivateKey prikey = keyMan.getPKCS8PrivateKey(privateKey);
			// 加密数据
			Signature signature = Signature.getInstance("DSA");
			signature.initSign(prikey);
			signature.update(this.signHelper.getContentBytes(toSignString,
					charset));
			byte signBytes[] = signature.sign();
			// 转换成String
			String sign = new String(Base64.encodeBase64(signBytes));
			rt.setSign(sign);
			// 向参数中添加sign信息
			Properties requestProperties = properties;
			//requestProperties.setProperty("sign_type", "DSA");
			requestProperties.setProperty("sign", sign);
			// 生成包含加密信息的URL参数
			String signURL = this.signHelper.genSignURL(requestProperties,
					charset);
			rt.setSignURL(signURL);
			rt.setSuccess(true);
		} catch (Exception e) {
			e.printStackTrace();
			rt.setErrorMessage(SignErrorMessage.SYSTEM_ERROR);
		}
		return rt;
	}
	/**
	 * 验证经过DSA方式加密的Properties内容，Properties中必须包含sign及sign_type
	 * 
	 * @param properties
	 * @param publicKey
	 * @param charset
	 * @return
	 */
	public SignatureResult checkDSASign(Properties properties,
			String publicKey, String charset) {
		SignatureResult rt = new SignatureResult();
		try {
			String sign = properties.getProperty("sign");
			String sign_type = properties.getProperty("sign_type");
			if (sign == null || sign.trim().length() == 0) {
				rt.setErrorMessage(SignErrorMessage.ILLEAGL_PARAMETER);
				return rt;
			}
			if (sign_type == null || !sign_type.equalsIgnoreCase("DSA")) {
				rt.setErrorMessage(SignErrorMessage.ILLEAGL_PARAMETER);
				return rt;
			}
			// 获取被签名的字符串,字符串中不包含sign及sign_type
			String toCheckString = this.signHelper.getSignatureContent(properties);
			// 转换得到被签名后数据
			byte signBytes[] = Base64.decodeBase64(sign.getBytes());

			Signature signature = Signature.getInstance("DSA");
			PublicKey pubKey = keyMan.getX509PublicKey(publicKey);
			signature.initVerify(pubKey);
			signature.update(this.signHelper.getContentBytes(toCheckString,
					charset));
			rt.setSuccess(signature.verify(signBytes));
		} catch (Exception e) {
			e.printStackTrace();
			rt.setErrorMessage(SignErrorMessage.SYSTEM_ERROR);
		}
		return rt;
	}
	
	/**
	 * 验证经过DSA方式加密的Properties内容，Properties中不包含sign_type
	 * 
	 * @param properties
	 * @param publicKey
	 * @param charset
	 * @return
	 */
	public SignatureResult checkDSASign2(Properties properties,
			String publicKey, String charset) {
		SignatureResult rt = new SignatureResult();
		try {
			String sign = properties.getProperty("sign");
			if (sign == null || sign.trim().length() == 0) {
				rt.setErrorMessage(SignErrorMessage.ILLEAGL_PARAMETER);
				return rt;
			}
			// 获取被签名的字符串,字符串中不包含sign及sign_type
			String toCheckString = this.signHelper.getSignatureContent(properties);
			// 转换得到被签名后数据
			byte signBytes[] = Base64.decodeBase64(sign.getBytes());

			Signature signature = Signature.getInstance("DSA");
			PublicKey pubKey = keyMan.getX509PublicKey(publicKey);
			signature.initVerify(pubKey);
			signature.update(this.signHelper.getContentBytes(toCheckString,
					charset));
			rt.setSuccess(signature.verify(signBytes));
		} catch (Exception e) {
			e.printStackTrace();
			rt.setErrorMessage(SignErrorMessage.SYSTEM_ERROR);
		}
		return rt;
	}
}
